﻿using System;
using System.ComponentModel;
using System.Drawing;
using System.Reactive.Linq;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using ImageProcessor.Shared;
using ImageProcessor.Shared.ImageExtensions;
using Color = System.Drawing.Color;

namespace ImageProcessor.Tim
{
    public class ContrastVM : ImageProcessorBaseVM
    {
        private double _contrast;
        private ImageSource _resultImage;

        public ContrastVM(MainViewModel mainVM) : base(mainVM)
        {
            Contrast = 0;
            
            Observable.FromEventPattern(this, "PropertyChanged")
                .Throttle(TimeSpan.FromMilliseconds(500))
                .Subscribe(eventPattern=>
                               {
                                   var sourceImage = MainVM.SourceImage as BitmapSource;
                                   if (sourceImage != null)
                                   {
                                       Bitmap temp = null;
                                       Dispatcher.Invoke(new Action(() => temp = sourceImage.BitmapSourceToBitmap()));;
                                       var contrastApplied = ApplyContrast(Contrast, temp);

                                       Dispatcher.BeginInvoke(new Action(() =>
                                                                             {
                                                                                 ResultImage = contrastApplied.BitmapToBitmapSource();
                                                                             }));
                                       
                                   }
                               });
        }

        public double Contrast
        {
            get { return _contrast; }
            set
            {
                if(_contrast == value)
                    return;
                _contrast = value;
                
                OnPropertyChanged("Contrast");                               
            }
        }

        public ImageSource ResultImage
        {
            get { return _resultImage; }
            private set
            {
                if (_resultImage == value)
                    return;
                _resultImage = value;
                OnPropertyChanged("ResultImage");
            }
        }

        protected override void Execute(object obj)
        {
            
        }

        protected override bool CanExecute(object obj)
        {
            return MainVM.SourceImage != null;
        }

        public Bitmap ApplyContrast(double contrast, Bitmap temp)
        {
            Bitmap bmap = (Bitmap)temp.Clone();
            if (contrast < -100) contrast = -100;
            if (contrast > 100) contrast = 100;
            contrast = (100.0 + contrast) / 100.0;
            contrast *= contrast;
            Color c;
            for (int i = 0; i < bmap.Width; i++)
            {
                for (int j = 0; j < bmap.Height; j++)
                {
                    c = bmap.GetPixel(i, j);
                    double pR = c.R / 255.0;
                    pR -= 0.5;
                    pR *= contrast;
                    pR += 0.5;
                    pR *= 255;
                    if (pR < 0) pR = 0;
                    if (pR > 255) pR = 255;

                    double pG = c.G / 255.0;
                    pG -= 0.5;
                    pG *= contrast;
                    pG += 0.5;
                    pG *= 255;
                    if (pG < 0) pG = 0;
                    if (pG > 255) pG = 255;

                    double pB = c.B / 255.0;
                    pB -= 0.5;
                    pB *= contrast;
                    pB += 0.5;
                    pB *= 255;
                    if (pB < 0) pB = 0;
                    if (pB > 255) pB = 255;

                    bmap.SetPixel(i, j,
                        Color.FromArgb((byte)pR, (byte)pG, (byte)pB));
                }
            }
            return bmap;
        }
    }
}